package com.kyrie.lib_sys.utils.learn.TimeDemo;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

//1:  用户自由选择输入1个或多个时间点, 每个时间点都可以单独跳过（留空不输入）,允许处理不完整的时间记录;

//2:  对单个数据的从小到大顺序校验, 只对实际输入的时间点进行校验

//3:  每输入一条新记录，立即与已存在的所有时间点进行校验,维护一个全局有序时间点列表(allTimePoints),新记录的时间点必须晚于所有已存在的时间点;

//4:  对存在时间重叠的报错时间点根据value获取key  实时获取具体报错地方

public class TimeDemo05 {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static List<Map<String, LocalDateTime>> timeList = new ArrayList<>();

    // 存储所有时间点的列表，用于快速验证时间重叠
    private static final List<LocalDateTime> allTimePoints = new ArrayList<>();

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入要添加的时间记录数量：");
        int count = Integer.parseInt(scanner.nextLine());

        for (int i = 0; i < count; i++) {
            System.out.println("第" + (i + 1) + "条记录：");

            Map<String, LocalDateTime> record = new LinkedHashMap<>();

            // 灵活输入各个时间点
            inputTimePoint(scanner, record, "prepareTime");
            inputTimePoint(scanner, record, "travelTime");
            inputTimePoint(scanner, record, "startTime");
            inputTimePoint(scanner, record, "completeTime");

            // 校验当前记录内部时间顺序
            if (!validateSingleRecord(record)) {
                i--; // 重新输入当前记录
                continue;
            }

            // 校验与已有记录的时间重叠
            if (!validateCrossRecords(record)) {
                i--; // 重新输入当前记录
                continue;
            }

            // 校验通过，添加到列表
            timeList.add(record);
            updateAllTimePoints(record);
            System.out.println("记录添加成功！");
        }

        System.out.println("所有记录添加完成，最终校验结果：" + timeCheck(timeList));
    }

    /**
     * 输入单个时间点
     */
    private static void inputTimePoint(Scanner scanner, Map<String, LocalDateTime> record, String fieldName) {
        while (true) {
            System.out.print("请输入 " + fieldName + "（格式 yyyy-MM-dd HH:mm:ss，留空跳过）：");
            String input = scanner.nextLine().trim();

            if (input.isEmpty()) {
                return; // 跳过该时间点
            }

            try {
                LocalDateTime time = LocalDateTime.parse(input, formatter);
                record.put(fieldName, time);
                return;
            } catch (DateTimeParseException e) {
                System.out.println("时间格式错误，请重新输入！");
            }
        }
    }

    /**
     * 工时时间校验
     * @param timeList 时间记录列表
     * @return true-校验通过 false-校验失败
     */
    public static boolean timeCheck(List<Map<String, LocalDateTime>> timeList) {
        if (timeList == null || timeList.isEmpty()) {
            System.out.println("timeList为空");
            return false;
        }

        // 已经实时校验过，这里只需汇总  save
        System.out.println("所有时间点校验通过，无重叠");
        return true;
    }


    /**
     * 如果是第一次填写工时单时
     * 校验单个记录内部的时间顺序
     */
    private static boolean validateSingleRecord(Map<String, LocalDateTime> record) {
        List<LocalDateTime> times = new ArrayList<>(record.values());

        //第一次填写,且只存在一个时间点, 默认不可能存在时间重叠
        if (times.size() < 2) {
            return true;
        }

        //存在多个时间点时，进行时间顺序校验
        for (int i = 0; i < times.size() - 1; i++) {
            if (!times.get(i + 1).isAfter(times.get(i))) {   //after 如果后一个时间小于等于前一个时间
                System.out.println("错误：时间顺序不正确,存在时间重叠: 错误的时间点信息是 - " +
                        getKeyByValue(record, times.get(i)) + "(" + times.get(i) + ") " +
                        "不应晚于 " +
                        getKeyByValue(record, times.get(i + 1)) + "(" + times.get(i + 1) + ")");
                return false;
            }
        }
        return true;
    }

    /**
     * 如果是多次填写工时单时
     * 校验跨记录的时间顺序
     */
    private static boolean validateCrossRecords(Map<String, LocalDateTime> newRecord) {
        if (allTimePoints.isEmpty()) {
            return true;
        }

        // 获取新记录中的所有时间点
        List<LocalDateTime> newTimes = new ArrayList<>(newRecord.values());

        // 检查新时间点是否与已有时间点重叠
        for (LocalDateTime newTime : newTimes) {
            for (LocalDateTime existingTime : allTimePoints) {
                if (newTime.equals(existingTime)) {
                    System.out.println("错误：时间点冲突 - " + newTime + " 与已有时间点完全重叠");
                    return false;
                }

                if (!allTimePoints.isEmpty() && newTime.isBefore(allTimePoints.get(allTimePoints.size() - 1))) {
                    System.out.println("错误：存在时间重叠冲突 - " + newTime +
                            " 不能早于最后一个已记录时间点 " + allTimePoints.get(allTimePoints.size() - 1));
                    return false;
                }
            }
        }

        return true;
    }


    /**
     * 更新全局时间点列表
     */
    private static void updateAllTimePoints(Map<String, LocalDateTime> record) {
        //将所有时间点添加到全局时间点列表中
        allTimePoints.addAll(record.values());
        // 保持时间点有序
        allTimePoints.sort(LocalDateTime::compareTo);
    }

    /**
     * 根据value获取key  用来获取具体重叠的时间点位置
     */
    private static String getKeyByValue(Map<String, LocalDateTime> map, LocalDateTime value) {
        for (Map.Entry<String, LocalDateTime> entry : map.entrySet()) {
            if (entry.getValue().equals(value)) {
                return entry.getKey();
            }
        }
        return null;
    }
}